#include "Graph.h"
#include "MakeGraph.h"
#include <typeinfo>
const int NUMBER_OF_TESTS = 100;
const int MAX_SIZE = 77;

void TestGetNumberOfVertices(const Graph &graph, int vertices_number){
    if(vertices_number != graph.GetNumberOfVertices()){
        throw std::logic_error("GetNumberOfVertices ERROR : wrong answer");
    }
}

void TestGetNumberOfVertices(){
    for(int test = 0; test < NUMBER_OF_TESTS; test ++){
        int vertices_number = rand() % MAX_SIZE;
        std::vector<edge> edges = MakeRandomEdges(vertices_number);
        ConnectivityList list (vertices_number, edges);
        TestGetNumberOfVertices(list, vertices_number);
        ConnectivityMatrix matrix (vertices_number, edges);
        TestGetNumberOfVertices(matrix, vertices_number);
    }
}
void TestGetIncidentEdges(const Graph &graph, const std::vector<edge> &edges){
    for(int vertex = 0; vertex < graph.GetNumberOfVertices(); vertex++){
        std::set<edge> right_edges;
        for(int current_edge = 0; current_edge < edges.size(); current_edge++){
            if(edges[current_edge].from == vertex){
                right_edges.insert(edges[current_edge]);
            }
        }
        std::vector<edge> got_edges = graph.GetIncidentEdges(vertex);
        std::set<edge> set_got_edges (got_edges.begin(), got_edges.end());
        if(set_got_edges.size() != got_edges.size()){
            throw std::logic_error("GetIncidentList ERROR : got edges not unique");
        }
        if(set_got_edges != right_edges){
            throw std::logic_error("GetIncidentEdges ERROR : wrong edges");
        }
    }
}

void TestGetIncidentEdges(){
    for(int test = 0 ; test < NUMBER_OF_TESTS; test ++){
        int vertices_number = rand() % MAX_SIZE;
        std::vector<edge> edges = MakeRandomEdges(vertices_number);
        ConnectivityList list (vertices_number, edges);
        TestGetIncidentEdges(list, edges);
        ConnectivityMatrix matrix(vertices_number, edges);
        TestGetIncidentEdges(matrix, edges);
    }
}

void TestConstructor(const Graph& graph, const std::vector<edge> &edges){
    std::set<edge> right_edges (edges.begin(), edges.end());
    std::set<edge> included_edges;
    for(int vertex = 0; vertex < graph.GetNumberOfVertices(); vertex++){
        std::vector<edge> incident_list = graph.GetIncidentEdges(vertex);
        for(int incident_edge = 0; incident_edge < incident_list.size(); incident_edge++){
            included_edges.insert(incident_list[incident_edge]);
        }
    }
    if(right_edges != included_edges){
        throw std::logic_error ("Wrong edges");
    }
}

void TestConstructor(){
    for(int test = 0; test < NUMBER_OF_TESTS; test++){
        int vertices_number = rand() % MAX_SIZE;
        std::vector <edge> edges = MakeRandomEdges(vertices_number);
        ConnectivityList list (vertices_number, edges);
        TestConstructor(list, edges);
        ConnectivityMatrix matrix (vertices_number, edges);
        TestConstructor(matrix, edges);
    }
}


void TestMakeCompactGraph(){
    for(int test = 0; test < NUMBER_OF_TESTS;test++){
        int vertices_number = rand() % MAX_SIZE + 100;
        std::vector<edge> edges = MakeFullGraphEdges(vertices_number);
        std::auto_ptr<Graph>  full_graph = MakeCompactGraph(vertices_number, edges);
        if(typeid(*full_graph) != typeid(ConnectivityMatrix)){
            throw std::logic_error("MakeCompactGraph ERROR : wrong representation has been chosen");
        }
        edges.clear();
        std::auto_ptr<Graph> graph = MakeCompactGraph(vertices_number, edges);
        if(typeid(*graph) != typeid(ConnectivityList)){
            throw std::logic_error("MakeCompactGraph ERROR : wrong representation has been chosen");
        }
    }
}

void TestGetEdgeWeight(const Graph &graph, const std::vector<edge> &edges){
    int vertices_number = graph.GetNumberOfVertices();
    std::vector<std::vector<int > > right_weights (vertices_number, std::vector<int>(vertices_number, INFINITY));
    for(int current_edge = 0; current_edge < edges.size(); current_edge++){
        int from = edges[current_edge].from;
        int to = edges[current_edge].to;
        int weight = edges[current_edge].weight;
        right_weights[from][to] = weight;
    }
    std::vector<std::vector< int > > got_weights (vertices_number, std::vector<int> (vertices_number));
    for(int from = 0; from < vertices_number; from++){
        for(int to = 0; to < vertices_number; to++){
            if(right_weights[from][to] != graph.GetEdgeWeight(from,to)){
                throw std::logic_error("GetEdgeWeight ERROR : wrong answer");
            }
        }
    }
}


void TestGetEdgeWeight(){
    for(int test = 0; test < NUMBER_OF_TESTS; test++){
        int vertices_number = rand() % MAX_SIZE;
        std::vector<edge> edges = MakeRandomEdges(vertices_number);
        ConnectivityList list(vertices_number, edges);
        TestGetEdgeWeight(list, edges);
        ConnectivityMatrix matrix (vertices_number, edges);
        TestGetEdgeWeight(matrix, edges);
    }
}

void TestAllGraph(){
    TestConstructor();
    TestGetIncidentEdges();
    TestGetNumberOfVertices();
    TestMakeCompactGraph();
    TestGetEdgeWeight();
}
